package cn.lutu.lutuspringboot.exceptionHandler;






import cn.lutu.util.exception.ServiceException;
import cn.lutu.util.response.ResultVO;
import cn.lutu.util.response.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.naming.AuthenticationException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /*
    绑定异常，错误码：1002
     */
    @ExceptionHandler({BindException.class})
    public ResultVO bindException(BindException e){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("请求参数格式错误，");
        stringBuilder.append(e.getFieldError().getDefaultMessage());
        stringBuilder.append("！");
        String message = stringBuilder.toString();
        log.warn(message);
        return ResultVO.fail(StatusCode.ERROR_BAD_REQUEST, message);
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResultVO methodArgumentNotValidException(MethodArgumentNotValidException e){
        ObjectError objectError=e.getBindingResult().getAllErrors().get(0);
        return new ResultVO(StatusCode.VALIDATE_ERROR,objectError.getDefaultMessage());
    }

    @ExceptionHandler
    public ResultVO handleThrowable(Throwable e) {
        log.debug("全局异常处理器开始处理Throwable");
        log.debug("异常跟踪信息如下：", e);
        String message = "服务器忙，请稍后再试！【看到这句时，你应该检查服务器端的控制台，并在全局异常处理器中添加处理异常的方法】";
        return  new ResultVO(StatusCode.ERROR_UNKNOWN,message);
    }

    @ExceptionHandler
    public ResultVO handleConstraintViolationException(ConstraintViolationException e){
        log.debug("开始处理ConstraintViolationException异常");
        StringBuilder builder = new StringBuilder();
        Set<ConstraintViolation<?>> violationExceptionSet = e.getConstraintViolations();
        for(ConstraintViolation<?> constraintViolation: violationExceptionSet){
            builder.append(constraintViolation.getMessage());
        }
        String message = builder.toString();
        return new ResultVO(StatusCode.ERROR_BAD_REQUEST,message);

    }

    @ExceptionHandler
    public ResultVO handlerServiceException(ServiceException e){
        log.debug("开始处理ServiceException");
        return ResultVO.fail(e);
    }

    @ExceptionHandler
    public ResultVO handleDisabledException(DisabledException e) {
        log.debug("全局异常处理器开始处理DisabledException");
        log.debug("异常跟踪信息如下：", e);
        String message = "登录失败，该账户已被禁用";
        return ResultVO.fail(StatusCode.ERROR_AUTHORIZED_DISABLED, message);
    }

    @ExceptionHandler
    public ResultVO handleAuthenticationException(BadCredentialsException e) {
        log.debug("全局异常处理器开始处理AuthenticationException");
        String message = "登录失败，用户名或密码错误";
        log.warn(message);
        return ResultVO.fail(StatusCode.ERROR_AUTHORIZED, message);
    }
    @ExceptionHandler
    public ResultVO handleAccessDeniedException(AccessDeniedException e) {
        log.debug("全局异常处理器开始处理AccessDeniedException");
        String message = "操作失败，当前登录的账号无此操作权限！";
        return ResultVO.fail(StatusCode.ERROR_FORBIDDEN, message);
    }

    @ExceptionHandler
    public ResultVO handleInsufficientAuthenticationException(InsufficientAuthenticationException e){
        log.debug("全局异常处理器开始处理InsufficientAuthenticationException");
        String message = "你未登录请先登录！";
        return ResultVO.fail(StatusCode.ERROR_FORBIDDEN, message);
    }

    @ExceptionHandler
    public ResultVO handleException(Exception e){
        log.debug("全局异常处理器开始处理Exception",e);
        String message = "服务器忙,请稍后再试!";
        return ResultVO.fail(StatusCode.ERROR_UNKNOWN, message);
    }
}
